package com.chenfan.mcn.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.chenfan.common.config.Constant;
import com.chenfan.common.exception.BusinessException;
import com.chenfan.mcn.clients.baseinfo.BaseInfoClient;
import com.chenfan.mcn.clients.finance.FinanceClient;
import com.chenfan.mcn.clients.privilege.PrivilegeClient;
import com.chenfan.mcn.clients.privilege.SDepartment;
import com.chenfan.mcn.clients.privilege.ScompanyRes;
import com.chenfan.mcn.config.UserVoContextHolder;
import com.chenfan.mcn.constant.BillCodeCst;
import com.chenfan.mcn.constant.NumberCst;
import com.chenfan.mcn.dao.LiveContractCommodityMapper;
import com.chenfan.mcn.dao.LiveSettlementCommodityMapper;
import com.chenfan.mcn.dao.LiveStarSettlementDetailMapper;
import com.chenfan.mcn.dao.LiveStarSettlementMapper;
import com.chenfan.mcn.dao.StarBasicDataMapper;
import com.chenfan.mcn.dao.StarPlatformInfoMapper;
import com.chenfan.mcn.enums.*;
import com.chenfan.mcn.event.EventPublisher;
import com.chenfan.mcn.event.OperateLogEvent;
import com.chenfan.mcn.exception.McnErrorCode;
import com.chenfan.common.extension.validation.groups.Modify;
import com.chenfan.mcn.component.CodeGenerateHelper;
import com.chenfan.common.extension.lock.DistributedLockTemplate;
import com.chenfan.mcn.model.*;
import com.chenfan.mcn.model.dto.*;
import com.chenfan.mcn.model.rpc.ChargeClearCallback;
import com.chenfan.mcn.model.vo.*;
import com.chenfan.mcn.mq.producer.LiveStarSettlementMessageProducer;
import com.chenfan.mcn.service.*;
import com.chenfan.mcn.utils.BusinessAssert;
import com.chenfan.mcn.utils.CommonUtil;
import com.chenfan.mcn.utils.ValidatorUtil;
import com.chenfan.process.vo.ApprovalOperationVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

/**
 * @author wulg
 * @date 2023/3/21
 */
@SuppressWarnings({"deprecation", "AlibabaUndefineMagicConstant", "AlibabaMethodTooLong"})
@Slf4j
@Service
public class LiveStarSettlementServiceImpl implements LiveStarSettlementService, ApprovalCallbackService {

    @Autowired
    private LiveStarSettlementMapper liveStarSettlementMapper;

    @Autowired
    private LiveStarSettlementDetailMapper liveStarSettlementDetailMapper;

    @Autowired
    private ApprovalFlowService approvalFlowService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private FinanceClient financeClient;

    @Autowired
    private StarAccountInfoService starAccountInfoService;

    @Autowired
    private StarBasicDataMapper starBasicDataMapper;

    @Autowired
    private PrivilegeClient privilegeClient;

    @Autowired
    private BaseInfoClient baseInfoClient;

    @Autowired
    private LiveStarSettlementMessageProducer messageProducer;

    @Autowired
    private LiveContractCommodityMapper liveContractCommodityMapper;

    @Autowired
    private MessageInfoService messageInfoService;

    private static final String APPROVAL_KEY = Constant.AUTHORIZATION + ":" + "approval::live_star_settlement::";

    @Override
    public Page<LiveStarSettlementListVO> getPage(LiveStarSettlementSearchDTO searchDTO) {
        searchDTO.setAlias("lss.");
        searchDTO.setProcessIds(Arrays.asList(ApprovalEnum.LIVE_STAR_SETTLEMENT.getProcessId()));
        if (CollectionUtils.isNotEmpty(searchDTO.getFlowStatus())) {
            List<Long> allList = approvalFlowService.getSrcList(searchDTO.getFlowStatus(), searchDTO.getProcessIds());
            if (CollectionUtil.isEmpty(allList)) {
                return new Page<>();
            }
            searchDTO.setSrcIds(allList);
        }
        Page<LiveStarSettlementListVO> settlementPage = liveStarSettlementMapper.getPage(new Page<>(searchDTO.getPageNum(), searchDTO.getPageSize()), searchDTO);
        List<LiveStarSettlementListVO> settlementList = settlementPage.getRecords();
        if (CollectionUtils.isNotEmpty(settlementList)) {
            //查询FlowId
            List<Long> idList = settlementList.stream().map(LiveStarSettlementListVO::getId).collect(toList());
            Map<Long, Long> flowMap = approvalFlowService.getNewestFlowIds(idList, searchDTO.getProcessIds());
            if (MapUtils.isNotEmpty(flowMap)) {
                settlementList.forEach(settlementListVO -> {
                    settlementListVO.setFlowId(flowMap.get(settlementListVO.getId()));
                });
            }
            List<Long> flowList = settlementList.stream().map(LiveStarSettlementListVO::getFlowId).filter(Objects::nonNull).collect(toList());
            JSONObject flowMapping = approvalFlowService.getFlowStatus(flowList);
            settlementList.forEach(item -> {
                item.setFlowStatusName(CommonUtil.defaultString(flowMapping, item.getFlowId()));
                item.setApprovalStatusName(LiveStarSettlementStatusEnum.getStatusName(item.getApprovalStatus()));
            });
        }
        return settlementPage;
    }

    @Override
    public List<LiveStarSettlementExportVO> exportExcel(LiveStarSettlementSearchDTO searchDTO) {
        searchDTO.setAlias("lss.");
        searchDTO.setProcessIds(Arrays.asList(ApprovalEnum.LIVE_STAR_SETTLEMENT.getProcessId()));
        if (CollectionUtils.isNotEmpty(searchDTO.getFlowStatus())) {
            List<Long> allList = approvalFlowService.getSrcList(searchDTO.getFlowStatus(), searchDTO.getProcessIds());
            if (CollectionUtil.isEmpty(allList)) {
                return Collections.EMPTY_LIST;
            }
            searchDTO.setSrcIds(allList);
        }
        List<LiveStarSettlementExportVO> exportList = liveStarSettlementMapper.exportExcel(searchDTO);
        if (CollectionUtils.isNotEmpty(exportList)) {
            //查询我司签约主体名称
            List<ScompanyRes> companyResList = privilegeClient.getParList().getObj();
            Map<Long, String> companyMap = companyResList.stream().collect(Collectors.toMap(ScompanyRes::getCompanyId, ScompanyRes::getParentCompanyName));
            exportList.forEach(item -> {
                item.setCompanyContractSubject(companyMap.get(item.getContractingId()));
                item.setApprovalStatusName(LiveStarSettlementStatusEnum.getStatusName(item.getApprovalStatus()));
            });
        }
        return exportList;
    }

    @Override
    public List<LiveStarSettlementCommodityVO> exportDetail(LiveStarSettlementDetailQueryDTO queryDTO) {
        Page<LiveStarSettlementCommodityVO> page = new Page<>(1L, -1L);
        //不统计总数
        page.setSearchCount(false);
        List<LiveStarSettlementCommodityVO> settlementDetails = liveStarSettlementDetailMapper.getDetailPage(page, queryDTO).getRecords();
        if (CollectionUtils.isNotEmpty(settlementDetails)) {

            Set<Long> starPlatIds = settlementDetails.stream().map(x -> x.getStarPlatId()).collect(Collectors.toSet());
            List<StarPlatInfoVO> starPlatInfoVos = starPlatformInfoMapper.getByIds(new ArrayList<>(starPlatIds));
            Map<Long, StarPlatInfoVO> starPlatInfoVoMap = starPlatInfoVos.stream().collect(Collectors.toMap(x -> x.getId(), x -> x, (x, y) -> x));

            settlementDetails.stream().forEach(entity -> {
                StarPlatInfoVO starPlatInfoVo = starPlatInfoVoMap.get(entity.getStarPlatId());
                if (Objects.nonNull(starPlatInfoVo)) {
                    entity.setLivePlatformName(starPlatInfoVo.getPlatformName());
                }
                if (Objects.nonNull(entity.getCommissionRate())) {
                    entity.setCommissionRate(entity.getCommissionRate().multiply(BigDecimal.valueOf(100L)));
                }
            });
        }
        return settlementDetails;
    }

    @Override
    public LiveStarSettlementDetailVO detail(Long id, Boolean includeDetail) {
        LiveStarSettlement liveStarSettlement = this.getSettlement(id, true);
        LiveStarSettlementDetailVO detailVO = new LiveStarSettlementDetailVO();
        BeanUtils.copyProperties(liveStarSettlement, detailVO);
        //审批流信息
        Long flowId = approvalFlowService.getFlowId(id, ApprovalEnum.LIVE_STAR_SETTLEMENT.getProcessId());
        if (Objects.nonNull(flowId)) {
            detailVO.setFlowId(flowId);
            List<Long> flowList = new ArrayList<>(Collections.singletonList(flowId));
            JSONObject flowMapping = approvalFlowService.getFlowStatus(flowList);
            detailVO.setFlowStatusName(CommonUtil.defaultString(flowMapping, detailVO.getFlowId()));
        }
        String stringFlowIds = approvalFlowService.getStringFlowIds(id, ApprovalEnum.LIVE_STAR_SETTLEMENT.getProcessId());
        detailVO.setFlowIds(stringFlowIds);
        //获取红人昵称
        StarBasicData starBasicData = starBasicDataMapper.selectById(detailVO.getStarId());
        BusinessAssert.notNull(starBasicData, McnErrorCode.STAR_BASIC_DATA_IS_NULL);
        detailVO.setStarNickname(starBasicData.getStarNickname());
        ////获取账户信息
        StarSettlementAccountInfoVO starAccountInfoVO = new StarSettlementAccountInfoVO();
        if (Objects.nonNull(liveStarSettlement.getStarAccountId())) {
            StarAccountInfo starAccountInfo = starAccountInfoService.getById(liveStarSettlement.getStarAccountId());
            BusinessAssert.notNull(starAccountInfo, McnErrorCode.STAR_ACCOUNT_BASIC_DATA_IS_NULL);
            starAccountInfoVO.setAccountName(starAccountInfo.getAccountName());
            starAccountInfoVO.setStudioPayment(starAccountInfo.getStudioPayment());
            starAccountInfoVO.setAccountType(starAccountInfo.getAccountType());
            starAccountInfoVO.setAccountNumber(starAccountInfo.getAccountNumber());
            starAccountInfoVO.setAccountBranchBank(starAccountInfo.getAccountBranchBank());
            starAccountInfoVO.setAccountBank(starAccountInfo.getAccountBank());
            starAccountInfoVO.setAccountIdCard(starAccountInfo.getAccountIdCard());
            starAccountInfoVO.setAccountPhone(starAccountInfo.getAccountPhone());
            starAccountInfoVO.setAccountCity(starAccountInfo.getAccountCity());
            starAccountInfoVO.setAccountProvince(starAccountInfo.getAccountProvince());
        }
        detailVO.setStarAccountInfoVO(starAccountInfoVO);
        //查询所属部门名称
        Map<Long, SDepartment> sDepartmentMap = privilegeClient.getDepartmentByIds(Collections.singletonList(detailVO.getDepartmentId())).getObj();
        if (CommonUtil.containsKey(sDepartmentMap, detailVO.getDepartmentId())) {
            detailVO.setDepartmentName(sDepartmentMap.get(detailVO.getDepartmentId()).getDepartmentName());
        }
        //查询我司签约主体名称
        List<ScompanyRes> companyResList = privilegeClient.getParList().getObj();
        Map<Long, String> companyMap = companyResList.stream().collect(Collectors.toMap(ScompanyRes::getCompanyId, ScompanyRes::getParentCompanyName));
        detailVO.setCompanyContractSubject(companyMap.get(detailVO.getContractingId()));

        if (ObjectUtils.defaultIfNull(includeDetail, Boolean.FALSE).booleanValue()) {
            LiveStarSettlementDetailQueryDTO queryDTO = new LiveStarSettlementDetailQueryDTO();
            queryDTO.setId(liveStarSettlement.getId());
            List<LiveStarSettlementCommodityVO> settlementDetails = this.exportDetail(queryDTO);
            detailVO.setSettlementDetails(settlementDetails);
        }
        return detailVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long save(LiveStarSettlementSaveDTO saveDTO) {
        LiveStarSettlement liveStarSettlement = null;
        if (Objects.isNull(saveDTO.getId())) {
            liveStarSettlement = new LiveStarSettlement();
            BeanUtils.copyProperties(saveDTO, liveStarSettlement);
            liveStarSettlement.setSettlementCode(CodeGenerateHelper.getCode(BillCodeCst.LIVE_STAR_SETTLEMENT));
            liveStarSettlement.setTaxableAmount(BigDecimal.ZERO);
            liveStarSettlementMapper.insert(liveStarSettlement);
            this.addSettlementDetails(liveStarSettlement.getId(), saveDTO.getLiveCommodityIdList());
            saveDTO.setId(liveStarSettlement.getId());
        } else {
            liveStarSettlement = this.updateSettlement(saveDTO);
        }
        //更新汇总打款金额
        this.updateSummary(liveStarSettlement.getId());
        LiveStarSettlement entity = this.getSettlement(saveDTO.getId(), true);
        if (LiveStarSettlementStatusEnum.isApproval(saveDTO.getApprovalStatus())) {
            BusinessAssert.isTrue(liveStarSettlementDetailMapper.exist(Wrappers.lambdaQuery(LiveStarSettlementDetail.class)
                    .eq(LiveStarSettlementDetail::getSettlementId, entity.getId())
                    .eq(LiveStarSettlementDetail::getIsInvalid, NumberCst.ZERO)
                    .eq(LiveStarSettlementDetail::getIsDelete, NumberCst.ZERO)

            ), McnErrorCode.BUSINESS_ERROR, "结算单未添加商品信息，不允许提交审批！");
            stringRedisTemplate.opsForValue().set(APPROVAL_KEY + entity.getSettlementCode(), JSONObject.toJSONString(UserVoContextHolder.getUserVo()), 100, TimeUnit.DAYS);
            approvalFlowService.startProcess(saveDTO.getId(), entity.getSettlementCode(), ApprovalEnum.LIVE_STAR_SETTLEMENT, JSON.toJSONString(entity), null);
        }
        LiveStarSettlement finalLiveStarSettlement = liveStarSettlement;
        EventPublisher.post(OperateLogEvent.builder().businessId(liveStarSettlement.getId())
                .businessType(LogBusinessTypeEnum.LIVE_STAR_SETTLEMENT)
                .compare(finalLiveStarSettlement, entity)
                .build());
        return saveDTO.getId();
    }

    @Resource
    private LiveSettlementCommodityMapper liveSettlementCommodityMapper;

    /**
     * 添加结算明细
     *
     * @param settlementId
     * @param liveCommodityIdList
     */
    private void addSettlementDetails(Long settlementId, List<Long> liveCommodityIdList) {
        if (CollectionUtils.isEmpty(liveCommodityIdList)) {
            return;
        }
        List<LiveSettlementCommodity> commodities = liveSettlementCommodityMapper.selectBatchIds(liveCommodityIdList);

        if (CollectionUtils.isNotEmpty(commodities)) {
            commodities.forEach(e -> BusinessAssert.isTrue(NumberCst.ZERO.equals(e.getSettlementStatus()), McnErrorCode.PARAM_ERROR, "不允许添加结算中/已结算的结算商品"));
            List<LiveStarSettlementDetail> details = commodities.stream().map(e -> {
                LiveStarSettlementDetail detail = new LiveStarSettlementDetail();
                detail.setSettlementId(settlementId);
                detail.setLiveCommodityId(e.getId());
                detail.setIsInvalid(NumberCst.ZERO);
                detail.setLiveCommoditySnapshoot(JSONObject.toJSONString(e));
                BeanUtils.copyProperties(e, detail);
                detail.setLiveCommodityId(e.getId());
                return detail;
            }).collect(toList());
            liveStarSettlementDetailMapper.insertBatch(details);

            //将关联的结算商品置为1-结算中
            liveSettlementCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveSettlementCommodity.class)
                    .set(LiveSettlementCommodity::getSettlementStatus, NumberCst.ONE)
                    .set(LiveSettlementCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                    .set(LiveSettlementCommodity::getUpdateName, UserVoContextHolder.getUserName())
                    .set(LiveSettlementCommodity::getUpdateDate, new Date())
                    .in(LiveSettlementCommodity::getId, liveCommodityIdList)
                    .eq(LiveSettlementCommodity::getSettlementStatus, NumberCst.ZERO)
            );

            List<Long> comodityIds = commodities.stream().map(LiveSettlementCommodity::getLccId).collect(toList());
            List<LiveContractCommodity> liveContractCommodities = liveContractCommodityMapper.selectBatchIds(comodityIds);
            if (CollUtil.isNotEmpty(liveContractCommodities)) {
                for (LiveContractCommodity liveContractCommodity : liveContractCommodities) {
                    List<LiveSettlementCommodity> liveSettlementCommodities = liveSettlementCommodityMapper.selectList(Wrappers.lambdaQuery(LiveSettlementCommodity.class)
                            .in(LiveSettlementCommodity::getLccId, liveContractCommodity.getId()));
                    //如果结算商品没有已结算的，直播商品状态设置为结算中，否则设置为部分结算(因为这里新增了结算商品，所以对应的直播商品肯定不可能直接变更为全部结算)
                    Integer settledCount = liveSettlementCommodities.stream().filter(haveEndData ->
                            haveEndData.getSettlementStatus().equals(NumberCst.TWO)).collect(toList()).size();
                    if (0 == settledCount) {
                        liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                .set(LiveContractCommodity::getSettlementStatus, NumberCst.ONE)
                                .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                .set(LiveContractCommodity::getUpdateDate, new Date())
                                .eq(LiveContractCommodity::getId, liveContractCommodity.getId()));
                    } else {
                        liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                .set(LiveContractCommodity::getSettlementStatus, NumberCst.FOUR)
                                .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                .set(LiveContractCommodity::getUpdateDate, new Date())
                                .eq(LiveContractCommodity::getId, liveContractCommodity.getId()));
                    }
                }
            }

        }
    }

    /**
     * 更新结算明细
     *
     * @param saveDTO
     */
    private LiveStarSettlement updateSettlement(LiveStarSettlementSaveDTO saveDTO) {
        Long settlementId = saveDTO.getId();
        List<Long> liveCommodityIdList = saveDTO.getLiveCommodityIdList();
        LiveStarSettlement liveStarSettlement = this.getSettlement(settlementId, true);
        BusinessAssert.isTrue(LiveStarSettlementStatusEnum.anyMatch(liveStarSettlement.getApprovalStatus(),
                LiveStarSettlementStatusEnum.UN_COMMIT, LiveStarSettlementStatusEnum.REJECTED, LiveStarSettlementStatusEnum.CANCEL),
                McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "当前单据状态不允许编辑");
        liveStarSettlementMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveStarSettlement.class)
                .set(LiveStarSettlement::getApprovalStatus, saveDTO.getApprovalStatus())
                .set(LiveStarSettlement::getChargeAttachmentFile, saveDTO.getChargeAttachmentFile())
                .set(LiveStarSettlement::getStarId, saveDTO.getStarId())
                .set(LiveStarSettlement::getConfirmScreenshot, saveDTO.getConfirmScreenshot())
                .set(LiveStarSettlement::getSettlementDate, saveDTO.getSettlementDate())
                .set(LiveStarSettlement::getContractingId, saveDTO.getContractingId())
                .set(LiveStarSettlement::getAttachmentFile, saveDTO.getAttachmentFile())
                .set(LiveStarSettlement::getRemark, saveDTO.getRemark())
                .set(LiveStarSettlement::getStarAccountId, saveDTO.getStarAccountId())
                .set(LiveStarSettlement::getChargeAmount, saveDTO.getChargeAmount())
                .set(LiveStarSettlement::getPaymentRemark, saveDTO.getPaymentRemark())
                .set(LiveStarSettlement::getUpdateBy, UserVoContextHolder.getUserId())
                .set(LiveStarSettlement::getUpdateName, UserVoContextHolder.getUserName())
                .set(LiveStarSettlement::getUpdateDate, new Date())
                .eq(LiveStarSettlement::getId, settlementId));
        List<Long> oldCommodityIds = this.getCommodityIds(settlementId);
        if (CollectionUtils.isNotEmpty(oldCommodityIds)) {
            //1、删除原先老的明细
            liveStarSettlementDetailMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveStarSettlementDetail.class)
                    .set(LiveStarSettlementDetail::getIsDelete, NumberCst.ONE)
                    .set(LiveStarSettlementDetail::getUpdateBy, UserVoContextHolder.getUserId())
                    .set(LiveStarSettlementDetail::getUpdateName, UserVoContextHolder.getUserName())
                    .set(LiveStarSettlementDetail::getUpdateDate, new Date())
                    .in(LiveStarSettlementDetail::getSettlementId, settlementId)
                    .eq(LiveStarSettlementDetail::getIsDelete, NumberCst.ZERO));
            //2、解除商品关联
            liveSettlementCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveSettlementCommodity.class)
                    .set(LiveSettlementCommodity::getSettlementStatus, NumberCst.ZERO)
                    .set(LiveSettlementCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                    .set(LiveSettlementCommodity::getUpdateName, UserVoContextHolder.getUserName())
                    .set(LiveSettlementCommodity::getUpdateDate, new Date())
                    .in(LiveSettlementCommodity::getId, oldCommodityIds)
            );
            //3、回滚直播商品状态(直播商品关联的所有结算商品状态为待结算，状态回滚为待结算，否则回滚为部分结算)
            List<LiveSettlementCommodity> liveSettlementCommodities = liveSettlementCommodityMapper.selectList(Wrappers.lambdaQuery(LiveSettlementCommodity.class)
                    .in(LiveSettlementCommodity::getId, oldCommodityIds));
            if (CollUtil.isNotEmpty(liveSettlementCommodities)) {
                Map<Long, List<LiveSettlementCommodity>> lccIdSettlementCommodityMap = liveSettlementCommodities.stream().collect(Collectors.groupingBy(LiveSettlementCommodity::getLccId));
                for (Long key : lccIdSettlementCommodityMap.keySet()) {
                    List<LiveSettlementCommodity> liveCommoditiesByLccId = liveSettlementCommodityMapper.selectList(Wrappers.lambdaQuery(LiveSettlementCommodity.class)
                            .eq(LiveSettlementCommodity::getLccId, key));

                    Integer waitSettleCount = liveCommoditiesByLccId.stream().filter(haveEndData ->
                            haveEndData.getSettlementStatus().equals(NumberCst.ZERO)).collect(toList()).size();
                    Integer settledCount = liveCommoditiesByLccId.stream().filter(haveEndData ->
                            haveEndData.getSettlementStatus().equals(NumberCst.TWO)).collect(toList()).size();
                    // 结算商品状态全部为待结算 更改商品状态为待结算
                    if (waitSettleCount == liveCommoditiesByLccId.size()) {
                        log.info("---修改红人直播结算单时直播商品关联的结算商品全部为待结算,更改直播商品状态为待结算---");
                        liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                .set(LiveContractCommodity::getSettlementStatus, NumberCst.ZERO)
                                .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                .set(LiveContractCommodity::getUpdateDate, new Date())
                                .eq(LiveContractCommodity::getId, key)
                        );
                    } else if (0 == settledCount) {
                        //结算商品包含没有已结算的且不是全部为待结算，设置直播商品为结算中
                        liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                .set(LiveContractCommodity::getSettlementStatus, NumberCst.ONE)
                                .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                .set(LiveContractCommodity::getUpdateDate, new Date())
                                .eq(LiveContractCommodity::getId, key));
                    } else {
                        //结算商品包含已结算且包含结算中，设置直播商品为部分结算
                        liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                .set(LiveContractCommodity::getSettlementStatus, NumberCst.FOUR)
                                .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                .set(LiveContractCommodity::getUpdateDate, new Date())
                                .eq(LiveContractCommodity::getId, key));
                    }
                }
            }
        }
        if (CollectionUtils.isNotEmpty(liveCommodityIdList)) {
            this.addSettlementDetails(settlementId, liveCommodityIdList);
        }
        return liveStarSettlement;
    }

    /**
     * 更新打款汇总信息
     *
     * @param settlementId
     */
    private void updateSummary(Long settlementId) {
        LiveStarSettlementPaidSummaryVO summaryVO = liveStarSettlementDetailMapper.paidSummary(settlementId);
        if (Objects.nonNull(summaryVO)) {
            LiveStarSettlement updateSummary = new LiveStarSettlement();
            updateSummary.setId(settlementId);
            updateSummary.setSettlementTotalAmount(ObjectUtils.defaultIfNull(summaryVO.getSettlementTotalAmount(), BigDecimal.ZERO));
            updateSummary.setTransactedTotalAmount(ObjectUtils.defaultIfNull(summaryVO.getTransactedTotalAmount(), BigDecimal.ZERO));
            updateSummary.setSettlementTotalCommission(ObjectUtils.defaultIfNull(summaryVO.getSettlementTotalCommission(), BigDecimal.ZERO));
            liveStarSettlementMapper.updateById(updateSummary);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean changeStatus(Long id, Integer approvalStatus, String approvalRemark) {
        LiveStarSettlement entity = this.getSettlement(id, true);
        BusinessAssert.isFalse(LiveStarSettlementStatusEnum.isInvalid(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "该结算单已作废，不允许操作！");
        if (LiveStarSettlementStatusEnum.isApproval(approvalStatus)) {
            //详情页提起审批-校验参数
            LiveStarSettlementSaveDTO saveDTO = new LiveStarSettlementSaveDTO();
            BeanUtils.copyProperties(entity, saveDTO);
            saveDTO.setApprovalStatus(approvalStatus);
            ValidatorUtil.validate(saveDTO, Modify.class);
            BusinessAssert.isTrue(liveStarSettlementDetailMapper.exist(Wrappers.lambdaQuery(LiveStarSettlementDetail.class)
                            .eq(LiveStarSettlementDetail::getSettlementId, entity.getId()).eq(LiveStarSettlementDetail::getIsDelete, NumberCst.ZERO))
                    , McnErrorCode.PARAM_ERROR, "未关联商品-不允许提交审批！");
        } else {
            if (LiveStarSettlementStatusEnum.isInvalid(approvalStatus)) {
                if (LiveStarSettlementStatusEnum.anyMatch(entity.getApprovalStatus(),
                        LiveStarSettlementStatusEnum.UN_PAYBACK, LiveStarSettlementStatusEnum.PART_PAYBACK, LiveStarSettlementStatusEnum.ALL_PAYBACK)) {
                    //判断该单据是否能在财务模块费用表查询到非删除状态的费用
                    Integer relatedCount = financeClient.getInvalid(entity.getSettlementCode(), null, null).getObj();
                    BusinessAssert.isTrue(relatedCount <= 0, McnErrorCode.INVALID_FAILED);
                }
                //注意顺序
                //1、绑定的商品-结算状态变更
                List<Long> oldCommodityIds = this.getCommodityIds(entity.getId());
                if (CollectionUtils.isNotEmpty(oldCommodityIds)) {
                    log.info("-----结算单作废,更改结算商品为待结算-----");
                    //v1.23.0逻辑更改
                    liveSettlementCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveSettlementCommodity.class)
                            .set(LiveSettlementCommodity::getSettlementStatus, NumberCst.ZERO)
                            .set(LiveSettlementCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                            .set(LiveSettlementCommodity::getUpdateName, UserVoContextHolder.getUserName())
                            .set(LiveSettlementCommodity::getUpdateDate, new Date())
                            .in(LiveSettlementCommodity::getId, oldCommodityIds)
                            .in(LiveSettlementCommodity::getSettlementStatus, Arrays.asList(NumberCst.ONE)));
                    //根据直播商品id获取所有结算商品
                    List<LiveSettlementCommodity> liveSettlementCommodities = liveSettlementCommodityMapper.selectList(Wrappers.lambdaQuery(LiveSettlementCommodity.class)
                            .in(LiveSettlementCommodity::getId, oldCommodityIds));
                    if (CollUtil.isNotEmpty(liveSettlementCommodities)) {
                        Map<Long, List<LiveSettlementCommodity>> lccIdSettlementCommodityMap = liveSettlementCommodities.stream().collect(Collectors.groupingBy(LiveSettlementCommodity::getLccId));
                        for (Long key : lccIdSettlementCommodityMap.keySet()) {
                            List<LiveSettlementCommodity> liveCommoditiesByLccId = liveSettlementCommodityMapper.selectList(Wrappers.lambdaQuery(LiveSettlementCommodity.class)
                                    .eq(LiveSettlementCommodity::getLccId, key));
                            Integer waitSettleCount = liveCommoditiesByLccId.stream().filter(haveEndData ->
                                    haveEndData.getSettlementStatus().equals(NumberCst.ZERO)).collect(toList()).size();
                            Integer settledCount = liveCommoditiesByLccId.stream().filter(haveEndData ->
                                    haveEndData.getSettlementStatus().equals(NumberCst.TWO)).collect(toList()).size();
                            // 结算商品状态全部为待结算 更改商品状态为待结算
                            if (waitSettleCount == liveCommoditiesByLccId.size()) {
                                log.info("直播商品关联的结算商品全部为待结算,更改直播商品状态为待结算");
                                liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                        .set(LiveContractCommodity::getSettlementStatus, NumberCst.ZERO)
                                        .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                        .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                        .set(LiveContractCommodity::getUpdateDate, new Date())
                                        .eq(LiveContractCommodity::getId, key)
                                );
                            } else if (0 == settledCount) {
                                //结算商品包含没有已结算的且不是全部为待结算，设置直播商品为结算中
                                liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                        .set(LiveContractCommodity::getSettlementStatus, NumberCst.ONE)
                                        .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                        .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                        .set(LiveContractCommodity::getUpdateDate, new Date())
                                        .eq(LiveContractCommodity::getId, key));
                            } else {
                                //结算商品包含已结算且包含结算中，设置直播商品为部分结算
                                liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                        .set(LiveContractCommodity::getSettlementStatus, NumberCst.FOUR)
                                        .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                        .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                        .set(LiveContractCommodity::getUpdateDate, new Date())
                                        .eq(LiveContractCommodity::getId, key));
                            }
                        }
                    }
                    // liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                    //         .set(LiveContractCommodity::getSettlementStatus, NumberCst.ZERO)
                    //         .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                    //         .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                    //         .set(LiveContractCommodity::getUpdateDate, new Date())
                    //         .in(LiveContractCommodity::getId, oldCommodityIds)
                    //         .in(LiveContractCommodity::getSettlementStatus, Arrays.asList(NumberCst.ONE, NumberCst.TWO))
                    // );
                }
                //2、释放绑定的商品
                liveStarSettlementDetailMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveStarSettlementDetail.class)
                        .set(LiveStarSettlementDetail::getIsInvalid, NumberCst.ONE)
                        .set(LiveStarSettlementDetail::getUpdateBy, UserVoContextHolder.getUserId())
                        .set(LiveStarSettlementDetail::getUpdateName, UserVoContextHolder.getUserName())
                        .set(LiveStarSettlementDetail::getUpdateDate, new Date())
                        .eq(LiveStarSettlementDetail::getSettlementId, entity.getId()));

            } else if (LiveStarSettlementStatusEnum.isCancel(approvalStatus)) {
                BusinessAssert.isFalse(LiveStarSettlementStatusEnum.anyMatch(entity.getApprovalStatus(),
                        LiveStarSettlementStatusEnum.UN_PAYBACK, LiveStarSettlementStatusEnum.PART_PAYBACK, LiveStarSettlementStatusEnum.ALL_PAYBACK)
                        , McnErrorCode.PARAM_ERROR, "已审批通过-不允许撤回！");

            }
        }
        boolean result = liveStarSettlementMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveStarSettlement.class)
                .set(LiveStarSettlement::getApprovalStatus, approvalStatus)
                .set(LiveStarSettlementStatusEnum.isCancel(approvalStatus), LiveStarSettlement::getPaymentAmount, null)
                .set(LiveStarSettlementStatusEnum.isCancel(approvalStatus), LiveStarSettlement::getTaxableAmount, BigDecimal.ZERO)
                .set(LiveStarSettlement::getUpdateBy, UserVoContextHolder.getUserId())
                .set(LiveStarSettlement::getUpdateName, UserVoContextHolder.getUserName())
                .set(LiveStarSettlement::getUpdateDate, new Date())
                .eq(LiveStarSettlement::getId, entity.getId()));
        if (result) {
            //如果红人月度结算单撤回或作废，则撤回已提起的审批流程
            if (LiveStarSettlementStatusEnum.anyMatch(approvalStatus, LiveStarSettlementStatusEnum.CANCEL, LiveStarSettlementStatusEnum.INVALID)) {
                approvalFlowService.revokeProcess(entity.getId(), ApprovalEnum.LIVE_STAR_SETTLEMENT.getProcessId());
            } else if (LiveStarSettlementStatusEnum.isApproval(approvalStatus)) {
                stringRedisTemplate.opsForValue().set(APPROVAL_KEY + entity.getSettlementCode(), JSONObject.toJSONString(UserVoContextHolder.getUserVo()), 100, TimeUnit.DAYS);
                approvalFlowService.startProcess(entity.getId(), entity.getSettlementCode(), ApprovalEnum.LIVE_STAR_SETTLEMENT, JSON.toJSONString(entity), null);
            }
            //操作日志
            EventPublisher.post(OperateLogEvent.builder().businessId(entity.getId())
                    .businessType(LogBusinessTypeEnum.LIVE_STAR_SETTLEMENT)
                    .compare(entity, liveStarSettlementMapper.selectById(entity.getId()))
                    .build());
        }
        return result;
    }

    @Resource
    private StarPlatformInfoMapper starPlatformInfoMapper;

    @Override
    public Page<LiveStarSettlementCommodityVO> getDetailPage(LiveStarSettlementDetailQueryDTO queryDTO) {
        Page<LiveStarSettlementCommodityVO> pageResponse = liveStarSettlementDetailMapper.getDetailPage(new Page<>(queryDTO.getPageNum(), queryDTO.getPageSize()), queryDTO);
        //查询主播
        Set<Long> starPlatIds = pageResponse.getRecords().stream().map(x -> x.getStarPlatId()).collect(Collectors.toSet());
        List<StarPlatInfoVO> starPlatInfoVos = starPlatformInfoMapper.getByIds(new ArrayList<>(starPlatIds));
        Map<Long, StarPlatInfoVO> starPlatInfoVoMap = starPlatInfoVos.stream().collect(Collectors.toMap(x -> x.getId(), x -> x, (x, y) -> x));

        pageResponse.getRecords().stream().forEach(entity -> {
            StarPlatInfoVO starPlatInfoVo = starPlatInfoVoMap.get(entity.getStarPlatId());
            if (Objects.nonNull(starPlatInfoVo)) {
                entity.setLivePlatformName(starPlatInfoVo.getPlatformName());
            }
            if (Objects.nonNull(entity.getCommissionRate())) {
                entity.setCommissionRate(entity.getCommissionRate().multiply(BigDecimal.valueOf(100L)));
            }
        });
        return pageResponse;
    }

    @Override
    public LiveStarSettlement getSettlementByCode(String settlementCode, boolean verifyExist) {
        LiveStarSettlement entity = liveStarSettlementMapper.selectOne(Wrappers.lambdaQuery(LiveStarSettlement.class)
                .eq(LiveStarSettlement::getSettlementCode, settlementCode)
                .eq(LiveStarSettlement::getIsDelete, NumberCst.ZERO));
        if (verifyExist) {
            BusinessAssert.notNull(entity, McnErrorCode.DATA_NOT_FOUND, "该结算单不存在");
        }
        return entity;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updatePayback(ChargeClearCallback dto, Long settlementId) {
        BigDecimal paybackAmount = dto.getPaybackAmount();
        MessageTopicEnum topicEnum = MessageTopicEnum.PAYBACK_CALLBACK_JS;
        LiveStarSettlement liveStarSettlement = this.getSettlement(settlementId, true);
        BusinessAssert.notNull(liveStarSettlement, McnErrorCode.DATA_NOT_FOUND, String.format("【%s】查询不到该结算单", topicEnum.getDesc()));
        BusinessAssert.isTrue(LiveStarSettlementStatusEnum.anyMatch(liveStarSettlement.getApprovalStatus(),
                LiveStarSettlementStatusEnum.UN_PAYBACK, LiveStarSettlementStatusEnum.PART_PAYBACK),
                McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "结算单状态-非待打款或部分打款");
        //是否冲销
        boolean isChargeAgainst = paybackAmount.compareTo(BigDecimal.ZERO) == -1;
        Date now = new Date();
        //更新收入合同已开票金额
        LiveStarSettlement updateEntity = new LiveStarSettlement();
        updateEntity.setPaybackAmount(paybackAmount.add(ObjectUtils.defaultIfNull(liveStarSettlement.getPaybackAmount(), BigDecimal.ZERO)));
        BusinessAssert.isTrue(updateEntity.getPaybackAmount().compareTo(BigDecimal.ZERO) != -1,
                McnErrorCode.PARAM_ERROR, String.format("【%s】计算后已开票金额为负数", topicEnum.getDesc()));
        if (BigDecimal.ZERO.compareTo(updateEntity.getPaybackAmount()) == 0) {
            updateEntity.setApprovalStatus(LiveStarSettlementStatusEnum.UN_PAYBACK.getCode());
        } else if (liveStarSettlement.getPaymentAmount().compareTo(updateEntity.getPaybackAmount()) == 1) {
            updateEntity.setApprovalStatus(LiveStarSettlementStatusEnum.PART_PAYBACK.getCode());
        } else if (liveStarSettlement.getPaymentAmount().compareTo(updateEntity.getPaybackAmount()) == 0) {
            updateEntity.setApprovalStatus(LiveStarSettlementStatusEnum.ALL_PAYBACK.getCode());
            updateEntity.setPaybackDate(ObjectUtils.defaultIfNull(dto.getPaybackDate(), now));
        } else {
            //理论上不存在 回款金额大于合同金额
            updateEntity.setApprovalStatus(LiveStarSettlementStatusEnum.ALL_PAYBACK.getCode());
            updateEntity.setPaybackDate(ObjectUtils.defaultIfNull(dto.getPaybackDate(), now));
        }
        String messageBody = JSONObject.toJSONString(dto);
        String messageKey = StringUtils.joinWith(isChargeAgainst ? "-" : "+", dto.getClearNo(), liveStarSettlement.getSettlementCode());
        String signature = CommonUtil.hmacMd5Hex(messageBody);
        MessageInfo messageInfo = MessageInfo.builder().messageTopic(topicEnum.name()).messageKey(messageKey)
                .tenantId(liveStarSettlement.getTenantId())
                .messageBody(messageBody).signature(signature).status(MessageStatusEnum.SUCCESS.getType()).build();
        if (!messageInfoService.addMessageInfo(messageInfo)) {
            MessageInfo entity = messageInfoService.selectOne(Wrappers.lambdaQuery(MessageInfo.class)
                    .eq(MessageInfo::getMessageTopic, topicEnum.name())
                    .eq(MessageInfo::getMessageKey, messageKey)
                    .eq(MessageInfo::getTenantId, liveStarSettlement.getTenantId())
                    .eq(MessageInfo::getIsDelete, Boolean.FALSE)
            );
            BusinessAssert.notNull(entity, McnErrorCode.BUSINESS_ERROR, String.format("【%s】数据幂等处理异常", topicEnum.getDesc()));
            //判断消息内容签名，如果相等，重复回调
            if (signature.equals(entity.getSignature())) {
                //也可以进一步比较金额
                return true;
            }
            ChargeClearCallback payload = JSONObject.parseObject(entity.getMessageBody(), ChargeClearCallback.class);
            throw new BusinessException(McnErrorCode.BUSINESS_ERROR.code(),
                    String.format("【%s】重复请求！上次回调：核销单号=%s，金额=%s，子结算单号=%s", topicEnum.getDesc(), payload.getClearNo(), payload.getPaybackAmount(), payload.getSourceBillCode()));
        }
        updateEntity.setId(liveStarSettlement.getId());
        updateEntity.setUpdateBy(dto.getOperatorId());
        updateEntity.setUpdateName(dto.getOperatorName());
        updateEntity.setUpdateDate(now);
        boolean result = liveStarSettlementMapper.updateById(updateEntity) > 0;
        if (result) {
            //如果结算单已打款-则更新商品已结算
            if (LiveStarSettlementStatusEnum.isAllPayback(updateEntity.getApprovalStatus())) {
                this.settlementedCommodity(settlementId);
            }
            //操作日志-结算单
            EventPublisher.post(OperateLogEvent.builder().businessId(liveStarSettlement.getId())
                    .businessType(LogBusinessTypeEnum.LIVE_STAR_SETTLEMENT)
                    .compare(liveStarSettlement, liveStarSettlementMapper.selectById(liveStarSettlement.getId()))
                    .build());
        }
        return result;
    }

    /**
     * 获取结算单
     *
     * @param settlementId
     * @param verifyExist
     * @return
     */
    private LiveStarSettlement getSettlement(Long settlementId, boolean verifyExist) {
        LiveStarSettlement entity = liveStarSettlementMapper.selectOne(Wrappers.lambdaQuery(LiveStarSettlement.class)
                .eq(LiveStarSettlement::getId, settlementId).eq(LiveStarSettlement::getIsDelete, NumberCst.ZERO));
        if (verifyExist) {
            BusinessAssert.notNull(entity, McnErrorCode.DATA_NOT_FOUND, "该结算单不存在");
        }
        return entity;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApprovalOperationVO changeApproval(ChangeApprovalDTO dto, Long billId) {
        LiveStarSettlement entity = this.getSettlement(billId, true);
        BusinessAssert.isFalse(LiveStarSettlementStatusEnum.isInvalid(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "单据已作废，不允许操作！");
        BusinessAssert.isTrue(LiveStarSettlementStatusEnum.isApproval(entity.getApprovalStatus()), McnErrorCode.DATA_OPERATION_NOT_SUPPORTED, "单据非审批中，不允许操作！");
        ApprovalOperationVO approvalOperationVO;
        if (!dto.getApprovalFlag().booleanValue()) {
            approvalOperationVO = approvalFlowService.approvalChange(dto.getApprovalId(), JSON.toJSONString(dto.getParamMap()), Boolean.FALSE, dto.getRemark());
        } else {
            String approvalParam = JSON.toJSONString(dto.getParamMap());
            if (CommonUtil.containsKeys(dto.getParamMap(), "paymentAmount", "taxableAmount")) {
                LiveStarSettlementFinanceExamineDTO financeExamineDTO = JSON.parseObject(approvalParam, LiveStarSettlementFinanceExamineDTO.class);
                financeExamineDTO.setApprovalId(dto.getApprovalId());
                financeExamineDTO.setSettlementId(entity.getId());
                ValidatorUtil.validate(financeExamineDTO);
                liveStarSettlementMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveStarSettlement.class)
                        .set(LiveStarSettlement::getPaymentAmount, financeExamineDTO.getPaymentAmount())
                        .set(LiveStarSettlement::getTaxableAmount, financeExamineDTO.getTaxableAmount())
                        .set(LiveStarSettlement::getUpdateBy, UserVoContextHolder.getUserId())
                        .set(LiveStarSettlement::getUpdateName, UserVoContextHolder.getUserName())
                        .set(LiveStarSettlement::getUpdateDate, new Date())
                        .eq(LiveStarSettlement::getId, entity.getId()));
                approvalOperationVO = approvalFlowService.approvalChange(dto.getApprovalId(), approvalParam, Boolean.TRUE, dto.getRemark());
                if (approvalOperationVO.isSuccess()) {
                    //操作日志
                    EventPublisher.post(OperateLogEvent.builder().businessId(entity.getId())
                            .businessType(LogBusinessTypeEnum.LIVE_STAR_SETTLEMENT)
                            .compare(entity, liveStarSettlementMapper.selectById(billId))
                            .build());
                }
            } else if (CommonUtil.containsKeys(dto.getParamMap(), "confirmScreenshot")) {
                Object confirmScreenshot = CommonUtil.getMapValue(dto.getParamMap(), "confirmScreenshot");
                LiveStarSettlement updateLiveStarSettlement = new LiveStarSettlement();
                updateLiveStarSettlement.setId(entity.getId());
                updateLiveStarSettlement.setConfirmScreenshot(CommonUtil.defaultIfEmpty(confirmScreenshot, ""));
                liveStarSettlementMapper.updateById(updateLiveStarSettlement);
                approvalOperationVO = approvalFlowService.approvalChange(dto.getApprovalId(), approvalParam, Boolean.TRUE, dto.getRemark());
            } else {
                approvalOperationVO = approvalFlowService.approvalChange(dto.getApprovalId(), approvalParam, Boolean.TRUE, dto.getRemark());
            }
        }
        BusinessAssert.isTrue(approvalOperationVO.isSuccess(), McnErrorCode.FLOW_ERROR, approvalOperationVO.getMessage());
        return approvalOperationVO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void approvalCallback(ApprovalFlowDTO approvalFlowDTO, Boolean status) {
        LiveStarSettlement entity = this.getSettlement(approvalFlowDTO.getSrcId(), true);
        approvalFlowDTO.setSrcCode(entity.getSettlementCode());
        approvalFlowDTO.addSubmitInfoIfNull(entity);
        if (Objects.isNull(status)) {
            //审批流配置-接入待办
            return;
        }
        if (LiveStarSettlementStatusEnum.anyMatch(entity.getApprovalStatus(), LiveStarSettlementStatusEnum.UN_PAYBACK, LiveStarSettlementStatusEnum.REJECTED)) {
            log.error("直播红人结算单-流程审批结束重复回调，不做处理！approvalId={}", approvalFlowDTO.getApprovalId());
            return;
        }
        //流程审批结束
        Integer approvalStatus = ((Supplier<Integer>) () -> {
            if (status.booleanValue()) {
                return BigDecimal.ZERO.compareTo(entity.getPaymentAmount()) == 0 ?
                        LiveStarSettlementStatusEnum.ALL_PAYBACK.getCode() : LiveStarSettlementStatusEnum.UN_PAYBACK.getCode();
            }
            return LiveStarSettlementStatusEnum.REJECTED.getCode();
        }).get();
        BusinessAssert.isTrue(DistributedLockTemplate.execute(OperateLockEnum.LIVE_STAR_SETTLEMENT.generateKey(entity.getId()), () -> {
            Date now = new Date();
            boolean result = liveStarSettlementMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveStarSettlement.class)
                    .set(LiveStarSettlement::getApprovalStatus, approvalStatus)
                    .set(LiveStarSettlementStatusEnum.isAllPayback(approvalStatus), LiveStarSettlement::getPaybackAmount, BigDecimal.ZERO)
                    .set(LiveStarSettlementStatusEnum.isAllPayback(approvalStatus), LiveStarSettlement::getPaybackDate, now)
                    .set(LiveStarSettlement::getUpdateBy, approvalFlowDTO.getUserId())
                    .set(LiveStarSettlement::getUpdateName, approvalFlowDTO.getUserName())
                    .set(LiveStarSettlement::getUpdateDate, now)
                    .eq(LiveStarSettlement::getId, entity.getId()));
            if (result) {
                if (LiveStarSettlementStatusEnum.isAllPayback(approvalStatus)) {
                    //如果结算单已打款-则更新商品已结算
                    this.settlementedCommodity(entity.getId());
                }
                //操作日志
                EventPublisher.post(OperateLogEvent.builder().businessId(entity.getId())
                        .businessType(LogBusinessTypeEnum.LIVE_STAR_SETTLEMENT)
                        .compare(entity, liveStarSettlementMapper.selectById(entity.getId()))
                        .build());
            }
            return result;
        }), McnErrorCode.FLOW_CALLBACK_HANDLE_EXCEPTION);
        // 待回款(审批通过) => 生成费用推送财务系统
        if (LiveStarSettlementStatusEnum.unPackback(approvalStatus)) {
            messageProducer.sendRecordToMq(entity.getId());
        }
        //发审批结束通知
        approvalFlowService.sendNotify(approvalFlowDTO, entity.getId(), entity.getSettlementCode(),
                ApprovalEnum.LIVE_STAR_SETTLEMENT, status, entity.getCreateBy(), entity.getCreateName());
    }

    /**
     * 获取结算单关联的商品ID
     *
     * @param settlementId
     * @return
     */
    private List<Long> getCommodityIds(Long settlementId) {
        List<LiveStarSettlementDetail> oldDetails = liveStarSettlementDetailMapper.selectList(Wrappers.lambdaQuery(LiveStarSettlementDetail.class)
                .select(LiveStarSettlementDetail::getLiveCommodityId)
                .eq(LiveStarSettlementDetail::getSettlementId, settlementId)
                .eq(LiveStarSettlementDetail::getIsDelete, NumberCst.ZERO));
        if (CollectionUtils.isEmpty(oldDetails)) {
            return null;
        }
        return oldDetails.stream().map(LiveStarSettlementDetail::getLiveCommodityId).distinct().collect(toList());
    }

    /**
     * 已结算商品
     *
     * @param settlementId
     */
    private void settlementedCommodity(Long settlementId) {
        //如果结算单已打款-则更新商品已结算
        List<LiveStarSettlementDetail> liveStarSettlementDetails = liveStarSettlementDetailMapper.selectList(Wrappers.lambdaQuery(LiveStarSettlementDetail.class)
                .select(LiveStarSettlementDetail::getLiveCommodityId)
                .eq(LiveStarSettlementDetail::getSettlementId, settlementId)
                .eq(LiveStarSettlementDetail::getIsDelete, NumberCst.ZERO));
        List<Long> liveCommodityIds = CommonUtil.defaultList(liveStarSettlementDetails.stream().map(LiveStarSettlementDetail::getLiveCommodityId).distinct().collect(toList()));
        if (CollectionUtils.isNotEmpty(liveCommodityIds)) {
            log.info("-----结算单为已打款,更改结算商品为已结算-----");
            //v1.23.0逻辑更改
            liveSettlementCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveSettlementCommodity.class)
                    .set(LiveSettlementCommodity::getSettlementStatus, NumberCst.TWO)
                    .set(LiveSettlementCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                    .set(LiveSettlementCommodity::getUpdateName, UserVoContextHolder.getUserName())
                    .set(LiveSettlementCommodity::getUpdateDate, new Date())
                    .in(LiveSettlementCommodity::getId, liveCommodityIds)
                    .in(LiveSettlementCommodity::getSettlementStatus, Arrays.asList(NumberCst.ONE)));
            //根据直播商品id获取所有结算商品
            List<LiveSettlementCommodity> liveSettlementCommodities = liveSettlementCommodityMapper.selectList(Wrappers.lambdaQuery(LiveSettlementCommodity.class)
                    .in(LiveSettlementCommodity::getId, liveCommodityIds));
            if (CollUtil.isNotEmpty(liveSettlementCommodities)) {
                Map<Long, List<LiveSettlementCommodity>> lccIdSettlementCommodityMap = liveSettlementCommodities.stream().collect(Collectors.groupingBy(LiveSettlementCommodity::getLccId));
                for (Long key : lccIdSettlementCommodityMap.keySet()) {
                    List<LiveSettlementCommodity> liveCommoditiesByLccId = liveSettlementCommodityMapper.selectList(Wrappers.lambdaQuery(LiveSettlementCommodity.class)
                            .eq(LiveSettlementCommodity::getLccId, key));
                    Integer settingCount = liveCommoditiesByLccId.stream().filter(haveEndData ->
                            haveEndData.getSettlementStatus().equals(NumberCst.ONE)).collect(toList()).size();
                    Integer settledCount = liveCommoditiesByLccId.stream().filter(haveEndData ->
                            haveEndData.getSettlementStatus().equals(NumberCst.TWO)).collect(toList()).size();
                    Integer waitingCount = liveCommoditiesByLccId.stream().filter(haveEndData ->
                            haveEndData.getSettlementStatus().equals(NumberCst.ZERO)).collect(toList()).size();
                    // 结算商品状态全部为【已结算】，则更新直播商品状态为【已结算】
                    if (settledCount == liveCommoditiesByLccId.size()) {
                        log.info("直播商品关联的结算商品全部已结算,更改直播商品状态为已结算");
                        liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                .set(LiveContractCommodity::getSettlementStatus, NumberCst.TWO)
                                .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                .set(LiveContractCommodity::getUpdateDate, new Date())
                                .eq(LiveContractCommodity::getId, key)
                        );
                    }
                    // 结算商品状态全部不是【已结算】也全部不是【待结算】(即含有结算中的结算商品)，则直播商品更新为【部分结算】
                    if (settingCount > 0 || waitingCount > 0) {
                        log.info("直播商品关联的结算商品含有结算中的状态,更改直播商品状态为部分结算");
                        liveContractCommodityMapper.updateByNoStrategy(Wrappers.lambdaUpdate(LiveContractCommodity.class)
                                .set(LiveContractCommodity::getSettlementStatus, NumberCst.FOUR)
                                .set(LiveContractCommodity::getUpdateBy, UserVoContextHolder.getUserId())
                                .set(LiveContractCommodity::getUpdateName, UserVoContextHolder.getUserName())
                                .set(LiveContractCommodity::getUpdateDate, new Date())
                                .eq(LiveContractCommodity::getId, key)
                        );
                    }
                }
            }
        }
    }
}
